package videostreaminglinux.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;
import videostreaminglinux.VideoStreamingLinuxApp;
import videostreaminglinux.VideoStreamingLinuxView;

/**
 * Trida reprezentujici server. Prijima a zobrazuje snapshoty odesilane
 * klientem. Umi vsak v jedne chvili obsluhovat pouze jednoho klienta.
 *
 * @author Jiri Masek, masekj5
 */
public class Server implements Runnable {
    private final String SERVER_URL = "btspp://localhost:" + VideoStreamingLinuxApp.RFCOMM_UUID + ";name=rfcommtest;authorize=false";

    private boolean isInit;

    private StreamConnectionNotifier notifier;
    private LocalDevice localDevice;
    private StreamConnection connection;
    private OutputStream output;
    private InputStream input;

    private Thread server;
    private VideoStreamingLinuxView videoStreamingLinuxView;

    /**
     * Vytvori novou instanci tridy <code>Server</code> a server ihned spusti.
     *
     * @param commandListener   Command Listener
     */
	public Server(VideoStreamingLinuxView videoStreamingLinuxView) {
        this.videoStreamingLinuxView = videoStreamingLinuxView;
        
        isInit = false;

        server = new Thread(this);
        server.start();
	}

    /**
     * Inicializuje Bluetooth zarizeni, navaze spojeni s klientem a prijima jim
     * zasilane snapshoty.
     */
	public void run() {
        if (!isInit) {
            // Inicializace Bluetooth
            try {
                connection = null;

                localDevice = LocalDevice.getLocalDevice();
                localDevice.setDiscoverable(DiscoveryAgent.GIAC);

                notifier = (StreamConnectionNotifier) Connector.open(SERVER_URL);
                
                // Pozastavi vlakno a vycka na spojeni
                connection = notifier.acceptAndOpen();

                output = connection.openOutputStream();
                input  = connection.openInputStream();

            } catch (BluetoothStateException e) {
                System.err.println("BluetoothStateException: " + e.getMessage());
            } catch (IOException e) {
                System.err.println("IOException: " + e.getMessage());
            }

            isInit = true;
        }

        if (connection != null) {
            try {
                do {
                    int length = input.read();
                    byte[] data = new byte[length];
                    length = 0;

                    // Assemble data
                    while (length != data.length) {
                        int ch = input.read(data, length, data.length - length);

                        if (ch == -1) {
                            throw new IOException("IOException: Can't read data");
                        }

                        length += ch;
                    }

                    data = new byte[VideoStreamingLinuxApp.byteArrayToInt(data)];
                    length = 0;

                    // Assemble data
                    while (length != data.length) {
                        int ch = input.read(data, length, data.length - length);

                        if (ch == -1) {
                            throw new IOException("IOException: Can't read data");
                        }

                        length += ch;
                    }
					
                    videoStreamingLinuxView.repaintImage(data);
                } while (true);
                
            } catch (IOException ex) {
                System.err.println("IOException: " + ex.getMessage());
            }
        }
	}
}
